package com.suke.money.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.money.suke.utils.Constants;
import com.money.suke.utils.PageModel;
import com.suke.money.mapper.BidInfoMapper;
import com.suke.money.mapper.FinanceAccountMapper;
import com.suke.money.mapper.LoanInfoMapper;
import com.suke.money.model.BidInfo;
import com.suke.money.model.LoanInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: liush
 * @CreateTime: 2022-11-20  16:27
 * @Description: 投资业务实现类
 */
//使用Dubbo独有的注解向服务中心注册服务，注意这个注解并不是创建一个实体类放到spring容器中，想要放入spring容器我们要使用@Componet注解
@Service(interfaceClass = BidInfoService.class, version = "1.0.0", timeout = 20000)
@Component
public class BidInfoServiceImpl implements BidInfoService {

    @Autowired
    BidInfoMapper bidInfoMapper;

    @Autowired
    LoanInfoMapper loanInfoMapper;

    @Autowired
    FinanceAccountMapper financeAccountMapper;

    @Autowired
    RedisTemplate redisTemplate;

    //查询 成交总金额
    @Override
    public Double queryBidInfoMoneySum() {
        //从redis缓存中获取 成交总金额
        Double bidInfoMoneySum = (Double) redisTemplate.opsForValue().get(Constants.BID_INFO_MONEY_SUM);
        //判断缓存中是否有数据
        if (bidInfoMoneySum == null) {
            //设置同步代码块
            synchronized (this) {
                //从redis缓存中获取 成交总金额
                bidInfoMoneySum = (Double) redisTemplate.opsForValue().get(Constants.BID_INFO_MONEY_SUM);
                //双重检测判断缓存中是否有数据
                if (bidInfoMoneySum == null) {
                    //从数据库查询 成交总金额
                    bidInfoMoneySum = bidInfoMapper.selectBidInfoMoneySum();
                    //将值存放到redis缓存中
                    redisTemplate.opsForValue().set(Constants.BID_INFO_MONEY_SUM, bidInfoMoneySum, 30, TimeUnit.SECONDS);
                    System.out.println("(×)成交总金额-缓存未命中");
                } else {
                    System.out.println("(√)成交总金额-缓存命中");
                }
            }
        } else {
            System.out.println("(√)成交总金额-缓存命中");
        }
        return bidInfoMapper.selectBidInfoMoneySum();
    }

    //查询总记录数 根据产品编号
    @Override
    public Long queryBidInfoNumsByLoanId(Integer loanId) {
        return bidInfoMapper.selectBidInfoNumsByLoanId(loanId);
    }

    //详情:根据产品编号 查询产品投资记录 进行分页
    @Override
    public List<BidInfo> queryBidInfosByLoanIdAndPageModel(Integer loanId, PageModel pageModel) {
        Map<String, Object> parasMap = new HashMap();
        parasMap.put("loanId", loanId);
        parasMap.put("start", (pageModel.getCunPage() <= 0 ? 1 : pageModel.getCunPage() - 1) * pageModel.getPageSize());
        parasMap.put("content", pageModel.getPageSize());
        return bidInfoMapper.selectBidInfosByLoanIdAndPageModel(parasMap);
    }

    //投资：投资
    @Override
    @Transactional
    public Integer invest(Map<String, Object> parasMap) {
        /*
         * 产品剩余可投金额减少
         * 判断是否满标
         * 账户余额减少
         * 添加投资记录
         * */

        //查询产品信息==》version
        LoanInfo loanIfo = loanInfoMapper.selectByPrimaryKey((Integer) parasMap.get("loanId"));
        if (loanIfo.getLeftProductMoney() < (Double) parasMap.get("bidMoney")) {
            return Constants.BID_LOAN_MONEY_NOT_ENOUGH;
        }
        parasMap.put("version", loanIfo.getVersion());

        //产品剩余可投金额减少
        int num = loanInfoMapper.updateLeftMoneyReduceForInvest(parasMap);
        if (num != 1) {
            //throw new RuntimeException("产品剩余可投金额减少失败");
            //手动回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Constants.BID_LOAN_MONEY_FAIL;
        }
        //判断是否满标
        LoanInfo loanInfo = loanInfoMapper.selectByPrimaryKey((Integer) parasMap.get("loanId"));
        if (loanInfo.getLeftProductMoney() == 0d && loanInfo.getProductStatus() != 1) {
            loanInfo.setProductStatus(1);
            loanInfo.setProductFullTime(new Date());
            num = loanInfoMapper.updateByPrimaryKeySelective(loanInfo);
            if (num != 1) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return Constants.BID_LOAN_STATE_FAIL;
            }
        }
        //账户余额减少
        num = financeAccountMapper.updateAvailableMoneyReduceForInvest(parasMap);
        if (num != 1) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Constants.BID_FINANCE_MONEY_FAIL;
        }
        //添加投资记录
        BidInfo bidInfo = new BidInfo();
        bidInfo.setBidMoney((Double) parasMap.get("bidMoney"));
        bidInfo.setBidStatus(1);
        bidInfo.setBidTime(new Date());
        bidInfo.setLoanId((Integer) parasMap.get("loanId"));
        bidInfo.setUid((Integer) parasMap.get("userId"));
        num = bidInfoMapper.insertSelective(bidInfo);
        if (num != 1) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Constants.BID_INSERT_FAIL;
        }

        return Constants.BID_SUCCESS;
    }
}
